import numpy as np


# 定义激活函数（这里使用Sigmoid函数）
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 定义Sigmoid函数的导数
def sigmoid_derivative(x):
    return x * (1.0 - x)


# 初始化参数
input_layer_neurons = 2  # 输入层神经元数量  
hidden_layer_neurons = 2  # 隐藏层神经元数量  
output_layer_neurons = 1  # 输出层神经元数量  

# 随机初始化权重  
weights_input_to_hidden = np.random.normal(scale=0.1, size=(input_layer_neurons, hidden_layer_neurons))
weights_hidden_to_output = np.random.normal(scale=0.1, size=(hidden_layer_neurons, output_layer_neurons))

# 训练数据  
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])  # 输入数据  
y = np.array([[0], [1], [1], [0]])  # 目标输出（标签）  


# 神经网络的前向传播
def forward_propagation(X, weights_input_to_hidden, weights_hidden_to_output):
    hidden_layer_activation = sigmoid(np.dot(X, weights_input_to_hidden))
    output_layer_activation = sigmoid(np.dot(hidden_layer_activation, weights_hidden_to_output))
    return hidden_layer_activation, output_layer_activation


# 神经网络的学习（这里仅作为示例，未实现完整的训练循环）
def train_network(X, y, weights_input_to_hidden, weights_hidden_to_output, epochs=1500, learning_rate=0.3):
    for epoch in range(epochs):
        # 前向传播  
        hidden_layer_activation, output_layer_activation = forward_propagation(X, weights_input_to_hidden,
                                                                               weights_hidden_to_output)

        # 计算输出层的误差  
        error = y - output_layer_activation

        # 计算输出层误差项（δ）  
        output_error_term = error * sigmoid_derivative(output_layer_activation)

        # 计算隐藏层误差项（需要输出层误差项和权重）  
        hidden_error = np.dot(output_error_term, weights_hidden_to_output.T)
        hidden_error_term = hidden_error * sigmoid_derivative(hidden_layer_activation)

        # 更新权重（这里只展示了输出层权重的更新，隐藏层类似）  
        weights_hidden_to_output += learning_rate * np.dot(hidden_layer_activation.T, output_error_term)
        # ...（隐藏层权重更新的代码）  

        # 这里可以添加额外的逻辑，比如打印损失、验证精度等  

    return weights_input_to_hidden, weights_hidden_to_output


# 训练网络（注意：这里仅展示了权重的更新逻辑，隐藏层权重的更新被省略了）
trained_weights_input_to_hidden, trained_weights_hidden_to_output = train_network(X, y, weights_input_to_hidden,
                                                                                  weights_hidden_to_output)


# 使用训练后的权重进行预测
def predict(X, weights_input_to_hidden, weights_hidden_to_output):
    _, output_layer_activation = forward_propagation(X, weights_input_to_hidden, weights_hidden_to_output)
    # 将sigmoid输出转换为0或1的预测（根据阈值）  
    return (output_layer_activation > 0.5).astype(int)


# 预测
predictions = predict(X, trained_weights_input_to_hidden, trained_weights_hidden_to_output)
print("Predictions:", predictions)

# 请注意，上面的代码是一个简化的示例，它仅展示了前向传播和权重更新的基本逻辑。
# 在真实的神经网络训练中，你需要添加反向传播（backpropagation）算法来完整地更新所有层的权重，并且通常会使用梯度下降的优化算法（如随机梯度下降SGD、Adam等）。
# 此外，还需要添加损失函数（如均方误差MSE、交叉熵损失等）来评估模型的性能